{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e06da9ff-297f-4e76-8495-0516cbddde05",
   "metadata": {},
   "source": [
    "# 实验8 基于全连接深度神经网络模型的手写识别及Wi-Fi动作感知"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea32482d-e2ad-4b25-af31-6af8812daec9",
   "metadata": {},
   "source": [
    "### 读取MNIST数据集和Wi-Fi动作感知数据集,并转化为相同的形式。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "51892181-a644-4e5e-a461-a9f9325d36db",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set size: 10000\n",
      "Training set size: 60000\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "label_size = 18 # Label size\n",
    "ticklabel_size = 14 # Tick label size\n",
    "\n",
    "class FlattenTransform:\n",
    "    def __call__(self, tensor):\n",
    "        ''' \n",
    "        Flatten tensor into an 1-D vector\n",
    "        '''\n",
    "        return tensor.view(-1)\n",
    "    \n",
    "# Define a transform to normalize the data\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(),\n",
    "    FlattenTransform()\n",
    "])\n",
    "\n",
    "# Load test data from the MNIST\n",
    "testset = torchvision.datasets.MNIST(root='./Data', train=False, download=False, transform=transform)\n",
    "print(f\"Test set size: {len(testset)}\")\n",
    "\n",
    "# Load training data from the MNIST\n",
    "trainset = torchvision.datasets.MNIST(root='./Data', train=True, download=False, transform=transform)\n",
    "print(f\"Training set size: {len(trainset)}\")\n",
    "\n",
    "# Rate of trX and cvX\n",
    "tr_cv_rate = 0.8\n",
    "\n",
    "# Create a list to store indices for each class\n",
    "class_indices = [[] for _ in range(10)]  # 10 classes in MNIST\n",
    "\n",
    "# Populate class_indices\n",
    "for idx, (_, label) in enumerate(trainset):\n",
    "    class_indices[label].append(idx)\n",
    "\n",
    "# Calculate the number of samples for each class in training and validation sets\n",
    "train_size_per_class = int(tr_cv_rate * min(len(indices) for indices in class_indices))\n",
    "val_size_per_class = min(len(indices) for indices in class_indices) - train_size_per_class\n",
    "\n",
    "# Create balanced train and validation sets\n",
    "train_indices = []\n",
    "val_indices = []\n",
    "for indices in class_indices:\n",
    "    train_indices.extend(indices[:train_size_per_class])\n",
    "    val_indices.extend(indices[train_size_per_class:train_size_per_class + val_size_per_class])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb35f350-e163-42b8-8d35-b0b2be6fb304",
   "metadata": {},
   "source": [
    "### 使用PyTorch的Dataset类和DataLoader类来构建数据加载器，以便在训练过程中批量加载数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2e77ecae-559e-4765-aebc-c369475b2003",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of training samples: 43360\n",
      "Number of cross-validation samples: 10850\n"
     ]
    }
   ],
   "source": [
    "# Create Subset datasets\n",
    "from torch.utils.data import Subset\n",
    "trX = Subset(trainset, train_indices)\n",
    "cvX = Subset(trainset, val_indices)\n",
    "\n",
    "print(f\"Number of training samples: {len(trX)}\")\n",
    "print(f\"Number of cross-validation samples: {len(cvX)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "15af6088-6e85-4ec7-adb4-08b7a29b7b76",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input_size is 784\n",
      "tensor([[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0.]])\n"
     ]
    }
   ],
   "source": [
    "batch_size = 42 # Define training batch\n",
    "\n",
    "def one_hot_collate(batch):\n",
    "    data = torch.stack([item[0] for item in batch])\n",
    "    labels = torch.tensor([item[1] for item in batch])\n",
    "    one_hot_labels = torch.zeros(labels.size(0), 10)  # 10 classes in MNIST\n",
    "    one_hot_labels.scatter_(1, labels.unsqueeze(1), 1)\n",
    "    return data, one_hot_labels\n",
    "\n",
    "trLoader = torch.utils.data.DataLoader(trX, batch_size=batch_size, shuffle=True, num_workers=0, collate_fn=one_hot_collate)\n",
    "cvLoader = torch.utils.data.DataLoader(cvX, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "teLoader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "\n",
    "# Get a batch of training data\n",
    "dataiter = iter(trLoader)\n",
    "data, labels = next(dataiter)\n",
    "\n",
    "input_size = data[0].numpy().shape[0]\n",
    "print(f'Input_size is {input_size}')\n",
    "print(labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "919e6746-8875-4938-9c95-51ff2e9f31d5",
   "metadata": {},
   "source": [
    "### 使用torch.nn模块定义一个全连接神经网络类（FNN），其中可以自定义隐藏层的数量和节点数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "c4c9926b-46b5-42a7-8bcb-efa11f5769be",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FNN(\n",
      "  (fc1): Linear(in_features=784, out_features=10, bias=True)\n",
      "  (relu1): ReLU()\n",
      "  (fc2): Linear(in_features=10, out_features=10, bias=True)\n",
      "  (relu2): ReLU()\n",
      "  (fc3): Linear(in_features=10, out_features=10, bias=True)\n",
      "  (softmax): Softmax(dim=1)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "import torch.nn as nn\n",
    "\n",
    "class FNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size, num_classes):\n",
    "        super(FNN, self).__init__()\n",
    "        self.fc1 = nn.Linear(input_size, hidden_size)\n",
    "        self.relu1 = nn.ReLU()\n",
    "        self.fc2 = nn.Linear(hidden_size, hidden_size)\n",
    "        self.relu2 = nn.ReLU()\n",
    "        self.fc3 = nn.Linear(hidden_size, num_classes)\n",
    "        self.softmax = nn.Softmax(dim=1)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.fc1(x)\n",
    "        x = self.relu1(x)\n",
    "        x = self.fc2(x)\n",
    "        x = self.relu2(x)\n",
    "        x = self.fc3(x)\n",
    "        out = self.softmax(x)\n",
    "        return out\n",
    "\n",
    "# Define the model parameters\n",
    "hidden_size = 10\n",
    "num_classes = 10  # MNIST has 10 classes (digits 0-9)\n",
    "\n",
    "# Instantiate the model\n",
    "model = FNN(input_size, hidden_size, num_classes)\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d9094a50-92c9-436b-9744-531cf5120130",
   "metadata": {},
   "source": [
    "### 使用Adam优化器来训练模型,设置合适的学习率和训练轮数（epochs）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5ed125fe-1201-4bf2-9ef8-ecbd0b6884f9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [1/21], Train Loss: 1.8329, CV Loss: 1.6782\n",
      "Epoch [2/21], Train Loss: 1.6569, CV Loss: 1.6514\n",
      "Epoch [3/21], Train Loss: 1.6414, CV Loss: 1.6456\n",
      "Epoch [4/21], Train Loss: 1.6354, CV Loss: 1.6416\n",
      "Epoch [5/21], Train Loss: 1.6309, CV Loss: 1.6391\n",
      "Epoch [6/21], Train Loss: 1.6276, CV Loss: 1.6401\n",
      "Epoch [7/21], Train Loss: 1.6254, CV Loss: 1.6367\n",
      "Epoch [8/21], Train Loss: 1.6235, CV Loss: 1.6362\n",
      "Epoch [9/21], Train Loss: 1.6215, CV Loss: 1.6338\n",
      "Epoch [10/21], Train Loss: 1.6201, CV Loss: 1.6343\n",
      "Epoch [11/21], Train Loss: 1.6189, CV Loss: 1.6331\n",
      "Epoch [12/21], Train Loss: 1.6171, CV Loss: 1.6358\n",
      "Epoch [13/21], Train Loss: 1.6046, CV Loss: 1.5845\n",
      "Epoch [14/21], Train Loss: 1.5556, CV Loss: 1.5608\n",
      "Epoch [15/21], Train Loss: 1.5452, CV Loss: 1.5566\n",
      "Epoch [16/21], Train Loss: 1.5411, CV Loss: 1.5547\n",
      "Epoch [17/21], Train Loss: 1.5382, CV Loss: 1.5519\n",
      "Epoch [18/21], Train Loss: 1.5359, CV Loss: 1.5506\n",
      "Epoch [19/21], Train Loss: 1.5346, CV Loss: 1.5506\n",
      "Epoch [20/21], Train Loss: 1.5328, CV Loss: 1.5489\n",
      "Epoch [21/21], Train Loss: 1.5318, CV Loss: 1.5487\n"
     ]
    }
   ],
   "source": [
    "# Define loss function and optimizer\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.Adam(model.parameters())\n",
    "\n",
    "# Lists to store losses\n",
    "train_losses = []\n",
    "cv_losses = []\n",
    "\n",
    "# Number of epochs\n",
    "num_epochs = 21\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    model.train()\n",
    "    batch_losses = []\n",
    "    \n",
    "    for batch_x, batch_y in trLoader:\n",
    "        # Forward pass\n",
    "        outputs = model(batch_x)\n",
    "        loss = criterion(outputs, batch_y)\n",
    "        \n",
    "        # Backward pass and optimize\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        \n",
    "        batch_losses.append(loss.item())\n",
    "    \n",
    "    # Calculate average training loss for this epoch\n",
    "    avg_train_loss = sum(batch_losses) / len(batch_losses)\n",
    "    train_losses.append(avg_train_loss)\n",
    "    \n",
    "    # Evaluate on cross-validation set\n",
    "    model.eval()\n",
    "    cv_batch_losses = []\n",
    "    with torch.no_grad():\n",
    "        for cv_x, cv_y in cvLoader:\n",
    "            cv_outputs = model(cv_x)\n",
    "            cv_loss = criterion(cv_outputs, cv_y)\n",
    "            cv_batch_losses.append(cv_loss.item())\n",
    "    \n",
    "    avg_cv_loss = sum(cv_batch_losses) / len(cv_batch_losses)\n",
    "    cv_losses.append(avg_cv_loss)\n",
    "    \n",
    "    print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {avg_train_loss:.4f}, CV Loss: {avg_cv_loss:.4f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7cc6d95-51dd-46cf-bd07-db8437a2552f",
   "metadata": {},
   "source": [
    "### 绘制学习曲线，分析模型的训练和验证损失以及准确率。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "7dd44b2e-1eff-423e-87bf-713bc1867f0b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy on training set: 93.65%\n",
      "Accuracy on cross-validation set: 91.38%\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1cAAAHUCAYAAADWedKvAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB/sklEQVR4nO3dd3gU5d7G8e9ustn0RkkBEnqQ3qs0QSmCICjYKAp6VOwdG3BQsYsVz1GKqC+iIhwLIF1UsKCAKEiREkpCJyG97Lx/bLJk00jflPtzXXPtzuwzs78ZJjG3z8wzJsMwDERERERERKRUzK4uQEREREREpDpQuBIRERERESkDClciIiIiIiJlQOFKRERERESkDChciYiIiIiIlAGFKxERERERkTKgcCUiIiIiIlIGFK5ERERERETKgMKViIiIiIhIGVC4EpEaw2QyFWnasGFDqb5n+vTpmEymEq27YcOGMqmhsps4cSINGzYsUlubzcaHH37IwIEDqV27NhaLhbp16zJs2DC++uorbDZb+RZbStu3b8dkMvHYY48V2Gbv3r2YTCbuueeeIm83v/OsX79+9OvX76LrHjx4EJPJxIIFC4r8fdl27tzJ9OnTOXjwYJ7PivPvWtZMJhN33XWXS75bRCSbu6sLEBGpKJs3b3aanzlzJuvXr2fdunVOy1u2bFmq75k8eTKDBw8u0bodO3Zk8+bNpa6hukhJSWHkyJGsWrWK6667jjlz5hAaGsrJkydZuXIl1157LYsXL2bEiBGuLrVA7dq1o1OnTixcuJBnn30WNze3PG3mz58PwKRJk0r1Xe+8806p1i+KnTt3MmPGDPr165cnSD311FPce++95V6DiEhlpXAlIjVG9+7dnebr1KmD2WzOszy3pKQkvL29i/w99evXp379+iWq0d/f/6L11CQPPPAA3377LR988AHjx493+mzUqFE8/PDDJCcnF7h+eno6JpMJd3fX/udu0qRJ3HnnnaxYsYJhw4Y5fZaZmcnChQvp1KkT7dq1K9X3uDqUN2nSxKXfLyLiarosUEQkh379+tG6dWs2btxIz5498fb25pZbbgFg8eLFXHHFFYSFheHl5cUll1zCY489RmJiotM28rtcq2HDhgwbNoyVK1fSsWNHvLy8aNGiBfPmzXNql99lgRMnTsTX15d9+/YxdOhQfH19adCgAQ8++CCpqalO6x85coRrrrkGPz8/AgMDufHGG/n111+LdAnYyZMnufPOO2nZsiW+vr7UrVuXyy67jO+//96pXfYlZS+//DKvvvoqjRo1wtfXlx49evDTTz/l2e6CBQuIiorCarVyySWXsHDhwkLryBYbG8v777/PoEGD8gSrbM2aNaNt27bAhWP34Ycf8uCDD1KvXj2sViv79u0DYN68ebRr1w5PT0+Cg4O5+uqr2bVrl9P29u/fz3XXXUd4eDhWq5WQkBAGDBjAtm3bHG3WrVtHv379qFWrFl5eXkRERDB69GiSkpIK3JcbbrgBLy8vRw9VTqtWreLo0aPFPs/yk99lgceOHWPMmDH4+fkREBDA2LFjiY2NzbPuli1buO6662jYsCFeXl40bNiQ66+/nkOHDjnaLFiwgGuvvRaA/v37Oy6lzT638rssMCUlhalTp9KoUSM8PDyoV68eU6ZM4dy5c07tivozUhpnzpzhzjvvpF69enh4eNC4cWOeeOKJPD9Hn332Gd26dSMgIABvb28aN27s+PcB+6WqzzzzDFFRUXh5eREYGEjbtm15/fXXy6xWEama1HMlIpJLTEwMN910E4888gjPPfccZrP9/0Pt3buXoUOHct999+Hj48Pff//NCy+8wC+//JLn0sL8bN++nQcffJDHHnuMkJAQ3n//fSZNmkTTpk3p06dPoeump6dz1VVXMWnSJB588EE2btzIzJkzCQgI4OmnnwYgMTGR/v37c+bMGV544QWaNm3KypUrGTt2bJH2+8yZMwBMmzaN0NBQEhISWLp0Kf369WPt2rV5/mh/++23adGiBbNnzwbsl4QNHTqUAwcOEBAQANj/GL/55psZMWIEr7zyCnFxcUyfPp3U1FTHcS3I+vXrSU9PZ+TIkUWqP9vUqVPp0aMH7777Lmazmbp16zJr1iwef/xxrr/+embNmsXp06eZPn06PXr04Ndff6VZs2YADB06lMzMTF588UUiIiI4deoUmzZtcgSBgwcPcuWVV9K7d2/mzZtHYGAgR48eZeXKlaSlpRXYwxkQEMDo0aNZvHgxJ0+epE6dOo7P5s+fj6enJzfccANQ+vMsp+TkZAYOHMixY8eYNWsWzZs355tvvsn3nDh48CBRUVFcd911BAcHExMTw5w5c+jSpQs7d+6kdu3aXHnllTz33HM8/vjjvP3223Ts2BEouMfK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525ubnTr1o23334bwNEmKiqKzp07O6aco+eFh4czePBgFi1axNtvv43ZbGbChAmOz8v6POvfvz/nz5/nyy+/dFr+f//3f07zJpMJwzDyfO/7779PZmam07LcPZSFyT62uY/9kiVLSExMLPDYl4cBAwaQkJDAsmXLnJZnn1v51WK1Wunbty8vvPACAFu3bs3TJjAwkGuuuYYpU6Zw5syZfB+uLCI1h3quRESKoGfPngQFBXH77bczbdo0LBYLH3/8Mdu3b3d1aQ4TJkzgtdde46abbuKZZ56hadOmrFixgm+//RbgoqPzDRs2jJkzZzJt2jT69u3L7t27+fe//02jRo3IyMgodj1ms5mZM2cyefJkrr76am699VbOnTvH9OnTi3RZINgvVdy/fz8TJ07k22+/5eqrryYkJIRTp06xevVq5s+fzyeffOK43ys/gYGBPPXUUzz++OOMHz+e66+/ntOnTzNjxgw8PT2ZNm0aYA+Sd911F9deey3NmjXDw8ODdevW8ccffzh6c959913WrVvHlVdeSUREBCkpKY6hwgcOHFikfZo0aRLffPONY5j5Bg0aOD4r6/Ns/PjxvPbaa4wfP55nn32WZs2asXz5csc5kc3f358+ffrw0ksvUbt2bRo2bMh3333H3LlzCQwMdGrbunVrAP773//i5+eHp6cnjRo1yveSvssvv5xBgwbx6KOPEh8fT69evRyjBXbo0IFx48aVaL8K8s8///D555/nWd6yZUvGjx/P22+/zYQJEzh48CBt2rThhx9+4LnnnmPo0KGOf7+nn36aI0eOMGDAAOrXr8+5c+d4/fXXne59Gz58OK1bt6Zz587UqVOHQ4cOMXv2bCIjIx0jT4pIDeXa8TRERFynoNECW7VqlW/7TZs2GT169DC8vb2NOnXqGJMnTzZ+//33PKOuFTRa4JVXXplnm7lHdytotMDcdRb0PdHR0caoUaMMX19fw8/Pzxg9erSxfPnyfEeMyy01NdV46KGHjHr16hmenp5Gx44djWXLluUZAS57tMCXXnopzzYAY9q0aU7L3n//faNZs2aGh4eH0bx5c2PevHl5tlmYjIwM44MPPjAuu+wyIzg42HB3dzfq1KljDBkyxPi///s/IzMz0zCMC8fus88+y3c777//vtG2bVvDw8PDCAgIMEaMGGH89ddfjs+PHz9uTJw40WjR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IyIiIiJS4yhcVRMe7mYa1/EBYLcuDRQRERERqXAKV9VI8+xBLTRioIiIiIhIhVO4qkZy3nclIiIiIiIVS+GqGskeMVCXBYqIiIiIVDyFq2oku+dq74kEMm0aMVBEREREpCIpXFUjDYK98bSYScuwceh0oqvLERERERGpURSuqhE3s8kxqIUeJiwiIiIiUrEUrqqZCyMGJri4EhERERGRmkXhqpqJUs+ViIiIiIhLKFxVMxoxUERERETENRSuqpnsnqsDpxJJzch0cTUiIiIiIjWHwlU1E+Jvxd/TnUybwT8nNGKgiIiIiEhFUbiqZkwmE1Ghuu9KRERERKSiKVxVQ44RAxWuREREREQqjMJVNeTouYpVuBIRERERqSgKV9WQeq5ERERERCqewlU1lD1i4JGzySSkZri4GhERERGRmkHhqhoK8vGgrp8VgL3qvRIRERERqRAKV9WURgwUEREREalYClfVlOO+q9gEF1ciIiIiIlIzKFxVU9n3XannSkRERESkYihcVVPNQzVioIiIiIhIRVK4qqaa1fUF4OT5VM4kprm4GhERERGR6k/hqprysbrTINgLgN16mLCIiIiISLlTuKrGdN+ViIiIiEjFUbiqxhwjBipciYiIiIiUO4WraszxrCtdFigiIiIiUu4UrqqxnD1XhmG4uBoRERERkepN4aoaa1LHF3ezifMpGcTGp7i6HBERERGRak3hqhrzcDfTqLYPoBEDRURERETKm8JVNZf9MGGNGCgiIiIiUr5cGq42btzI8OHDCQ8Px2QysWzZskLbT5w4EZPJlGdq1aqVo82CBQvybZOSUjMvi8sejn13bIKLKxERERERqd5cGq4SExNp164db731VpHav/7668TExDimw4cPExwczLXXXuvUzt/f36ldTEwMnp6e5bELlV5zPetKRERERKRCuLvyy4cMGcKQIUOK3D4gIICAgADH/LJlyzh79iw333yzUzuTyURoaGiZ1VmVReW4LDDTZuBmNrm4IhERERGR6qlK33M1d+5cBg4cSGRkpNPyhIQEIiMjqV+/PsOGDWPr1q2Fbic1NZX4+HinqbqICPbG6m4mNcNG9JkkV5cjIiIiIlJtVdlwFRMTw4oVK5g8ebLT8hYtWrBgwQK+/PJLFi1ahKenJ7169WLv3r0FbmvWrFmOXrGAgAAaNGhQ3uVXGDeziWYhvoBGDBQRERERKU9VNlwtWLCAwMBARo4c6bS8e/fu3HTTTbRr147evXvz6aef0rx5c958880CtzV16lTi4uIc0+HDh8u5+oql+65ERERERMqfS++5KinDMJg3bx7jxo3Dw8Oj0LZms5kuXboU2nNltVqxWq1lXWal4RgxUOFKRERERKTcVMmeq++++459+/YxadKki7Y1DINt27YRFhZWAZVVTo5BLXRZoIiIiIhIuXFpz1VCQgL79u1zzB84cIBt27YRHBxMREQEU6dO5ejRoyxcuNBpvblz59KtWzdat26dZ5szZsyge/fuNGvWjPj4eN544w22bdvG22+/Xe77U1llh6sDpxJJzcjE6u7m4opERERERKofl4arLVu20L9/f8f8Aw88AMCECRNYsGABMTExREdHO60TFxfHkiVLeP311/Pd5rlz57jtttuIjY0lICCADh06sHHjRrp27Vp+O1LJhfp74ufpzvmUDA6cSqRFqL+rSxIRERERqXZMhmEYri6isomPjycgIIC4uDj8/atHELlmzia2HDrL69e1Z0T7eq4uR0RERESkSihONqiS91xJ8TUP1YiBIiIiIiLlSeGqhnCMGBib4OJKRERERESqJ4WrGqK5Yzj2eBdXIiIiIiJSPSlc1RDNQ3wBOHwmmcTUDBdXIyIiIiJS/Shc1RC1fK3U9rU/KHnvCV0aKCIiIiJS1hSuapCoUHvvlR4mLCIiIiJS9hSuapAL910pXImIiIiIlDWFqxqkhYZjFxEREREpNwpXNYij50qXBYqIiIiIlDmFqxqkWVa4OnE+lbOJaS6uRkRERESkelG4qkF8re7UD/ICdGmgiIiIiEhZU7iqYaJCdN+ViIiIiEh5ULiqYZqHasRAEREREZHyoHBVw0RpUAsRERERkXKhcFXD5Bwx0DAMF1cjIiIiIlJ9KFzVMI3r+OBmNhGfksHx+FRXlyMiIiIiUm0oXNUwnhY3GtbyBnTflYiIiIhIWVK4qoGisga12KP7rkREREREyozCVQ0UFeIPqOdKRERERKQsKVzVQFGhvoCedSUiIiIiUpYUrmqg5jkeJGyzacRAEREREZGyoHBVA0XW8sHD3UxKuo3DZ5NcXY6IiIiISLWgcFUDuZlNNKtrvzRQDxMWERERESkbClc1VFSOSwNFRERERKT0FK5qqOZZw7H/rZ4rEREREZEyoXBVQ6nnSkRERESkbClc1VDZPVf7TyaSlmFzcTUiIiIiIlWfwlUNFR7gia/VnQybwYFTia4uR0RERESkylO4qqFMJhPNQ7JGDNSlgSIiIiIipaZwVYNFhfoDsEeDWoiIiIiIlJrCVQ0WpZ4rEREREZEyo3BVg2UPaqERA0VERERESk/hqgbLHo49+kwSSWkZLq5GRERERKRqU7iqwWr5Wqnt64FhwL4TCa4uR0RERESkSlO4quGaZ/Ve7dagFiIiIiIipaJwVcMpXImIiIiIlA2FqxouKmtQC40YKCIiIiJSOgpXNVx2z5VGDBQRERERKR2Fqxquedazro7Hp3IuKc3F1YiIiIiIVF0KVzWcn6eFeoFeAOw5rhEDRURERERKSuFKdN+ViIiIiEgZULiSC/ddacRAEREREZESU7gSokLt912p50pEREREpOQUrsRpxEDDMFxcjYiIiIhI1aRwJTSp44vZBOeS0jl5PtXV5YiIiIiIVEkKV4KnxY2GtX0AXRooIiIiIlJSClcCQFTWpYG7NaiFiIiIiEiJuDRcbdy4keHDhxMeHo7JZGLZsmWFtp84cSImkynP1KpVK6d2S5YsoWXLllitVlq2bMnSpUvLcS+qh+YKVyIiIiIipeLScJWYmEi7du146623itT+9ddfJyYmxjEdPnyY4OBgrr32WkebzZs3M3bsWMaNG8f27dsZN24cY8aM4eeffy6v3agWsp91tUeXBYqIiIiIlIjJqCTDw5lMJpYuXcrIkSOLvM6yZcsYNWoUBw4cIDIyEoCxY8cSHx/PihUrHO0GDx5MUFAQixYtKtJ24+PjCQgIIC4uDn9//2LtR1W170QCA1/9Di+LG3/NGITZbHJ1SSIiIiIiLlecbFCl77maO3cuAwcOdAQrsPdcXXHFFU7tBg0axKZNmwrcTmpqKvHx8U5TTdOwljce7maS0zM5cjbZ1eWIiIiIiFQ5VTZcxcTEsGLFCiZPnuy0PDY2lpCQEKdlISEhxMbGFritWbNmERAQ4JgaNGhQLjVXZu5uZprW0cOERURERERKqsqGqwULFhAYGJjvZYQmk/MlbYZh5FmW09SpU4mLi3NMhw8fLutyqwTddyUiIiIiUnLuri6gJAzDYN68eYwbNw4PDw+nz0JDQ/P0Up04cSJPb1ZOVqsVq9VaLrVWJRoxUERERESk5Kpkz9V3333Hvn37mDRpUp7PevTowerVq52WrVq1ip49e1ZUeVVWVKj9skD1XImIiIiIFJ9Le64SEhLYt2+fY/7AgQNs27aN4OBgIiIimDp1KkePHmXhwoVO682dO5du3brRunXrPNu899576dOnDy+88AIjRozgf//7H2vWrOGHH34o9/2p6rJ7rv45mUB6pg2LW5XM3iIiIiIiLuHSv563bNlChw4d6NChAwAPPPAAHTp04Omnnwbsg1ZER0c7rRMXF8eSJUvy7bUC6NmzJ5988gnz58+nbdu2LFiwgMWLF9OtW7fy3ZlqoF6gFz4ebqRnGhw8lejqckREREREqpRK85yryqQmPucq29Xv/MjW6HO8eX0HhrcLd3U5IiIiIiIuVWOecyVlLypEIwaKiIiIiJSEwpU40YiBIiIiIiIlU6JwdfjwYY4cOeKY/+WXX7jvvvv473//W2aFiWvoWVciIiIiIiVTonB1ww03sH79egBiY2O5/PLL+eWXX3j88cf597//XaYFSsXKDleHziSRnJbp4mpERERERKqOEoWrP//8k65duwLw6aef0rp1azZt2sT//d//sWDBgrKsTypYbV8rtXw8MAzYdyLB1eWIiIiIiFQZJQpX6enpWK1WANasWcNVV10FQIsWLYiJiSm76sQlHPdd6dJAEREREZEiK1G4atWqFe+++y7ff/89q1evZvDgwQAcO3aMWrVqlWmBUvF035WIiIiISPGVKFy98MIL/Oc//6Ffv35cf/31tGvXDoAvv/zScbmgVF0aMVBEREREpPjcS7JSv379OHXqFPHx8QQFBTmW33bbbXh7e5dZceIaUaG+gHquRERERESKo0Q9V8nJyaSmpjqC1aFDh5g9eza7d++mbt26ZVqgVLxmWT1XMXEpxCWnu7gaEREREZGqoUThasSIESxcuBCAc+fO0a1bN1555RVGjhzJnDlzyrRAqXj+nhbCAzwB9V6JiIiIiBRVicLV77//Tu/evQH4/PPPCQkJ4dChQyxcuJA33nijTAsU12geqvuuRERERESKo0ThKikpCT8/+x/fq1atYtSoUZjNZrp3786hQ4fKtEBxjagQjRgoIiIiIlIcJQpXTZs2ZdmyZRw+fJhvv/2WK664AoATJ07g7+9fpgWKa2jEQBERERGR4ilRuHr66ad56KGHaNiwIV27dqVHjx6AvRerQ4cO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pAwoXImIiIiIiJQBhSsREREREZEyoHAlIiIiIiJSBhSuREREREREyoDClYiIiIiISBlQuBIRERERESkDClciIiIiIiJlQOFKRERERESkDChciYiIiIiIlAGFKxERERERkTLg7uoCKiPDMACIj493cSUiIiIiIuJK2ZkgOyMURuEqH6dPnwagQYMGLq5EREREREQqg/PnzxMQEFBoG4WrfAQHBwMQHR190QMoxRcfH0+DBg04fPgw/v7+ri6n2tHxLV86vuVPx7h86fiWLx3f8qXjW750fPNnGAbnz58nPDz8om0VrvJhNttvRQsICNCJVY78/f11fMuRjm/50vEtfzrG5UvHt3zp+JYvHd/ypeObV1E7XDSghYiIiIiISBlQuBIRERERESkDClf5sFqtTJs2DavV6upSqiUd3/Kl41u+dHzLn45x+dLxLV86vuVLx7d86fiWnskoypiCIiIiIiIiUij1XImIiIiIiJQBhSsREREREZEyoHAlIiIiIiJSBhSuREREREREykCNDVfvvPMOjRo1wtPTk06dOvH9998X2v67776jU6dOeHp60rhxY959990KqrRqmTVrFl26dMHPz4+6desycuRIdu/eXeg6GzZswGQy5Zn+/vvvCqq66pg+fXqe4xQaGlroOjp3i6dhw4b5no9TpkzJt73O38Jt3LiR4cOHEx4ejslkYtmyZU6fG4bB9OnTCQ8Px8vLi379+vHXX39ddLtLliyhZcuWWK1WWrZsydKlS8tpDyq3wo5veno6jz76KG3atMHHx4fw8HDGjx/PsWPHCt3mggUL8j2nU1JSynlvKp+Lnb8TJ07Mc5y6d+9+0e3q/LW72PHN7zw0mUy89NJLBW5T569dUf4e0+/f8lEjw9XixYu57777eOKJJ9i6dSu9e/dmyJAhREdH59v+wIEDDB06lN69e7N161Yef/xx7rnnHpYsWVLBlVd+3333HVOmTOGnn35i9erVZGRkcMUVV5CYmHjRdXfv3k1MTIxjatasWQVUXPW0atXK6Tjt2LGjwLY6d4vv119/dTq+q1evBuDaa68tdD2dv/lLTEykXbt2vPXWW/l+/uKLL/Lqq6/y1ltv8euvvxIaGsrll1/O+fPnC9zm5s2bGTt2LOPGjWP79u2MGzeOMWPG8PPPP5fXblRahR3fpKQkfv/9d5566il+//13vvji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YTRs2LDAH/KaDsh3mj9/vqNN7uP7wgsvGE2aNDE8PT2NoKAg49JLLzW++eabii++Chg7dqwRFhZmWCwWIzw83Bg1apTx119/OT7XuVs2vv32WwMwdu/enecznb/Fkz1Ufe5pwoQJhmHYhwOeNm2aERoaalitVqNPnz7Gjh07nLbRt29fR/tsn332mREVFWVYLBajRYsWNTbMFnZ8Dxw4UODv5PXr1zu2kfv43nfffUZERITh4eFh1KlTx7jiiiuMTZs2VfzOVQKFHd+kpCTjiiuuMOrUqWNYLBYjIiLCmDBhghEdHe20DZ2/BbvY7wfDMIz//Oc/hpeXl3Hu3Ll8t6HzN39F+XtMv3/Lh8kwsu5uFxERERERkRKrcfdciYiIiIiIlAeFKxERERERkTKgcCUiIiIiIlIGFK5ERERERETKgMKViIiIiIhIGVC4EhERERERKQMKVyIiIiIiImVA4UpERERERKQMKFyJiIiUMZPJxLJly1xdhoiIVDCFKxERqVYmTpyIyWTKMw0ePNjVpYmISDXn7uoCREREytrgwYOZP3++0zKr1eqiakREpKZQz5WIiFQ7VquV0NBQpykoKAiwX7I3Z84chgwZgpeXF40aNeKzzz5zWn/Hjh1cdtlleHl5UatWLW677TYSEhKc2sybN49WrVphtVoJCwvjrrvucvr81KlTXH311Xh7e9OsWTO+/PLL8t1pERFxOYUrERGpcZ566ilGjx7N9u3buemmm7j++uvZtWsXAElJSQwePJigoCB+/fVXPvvsM9asWeMUnubMmcOUKVO47bbb2LFjB19++SVNmzZ1+o4ZM2YwZswY/vjjD4YOHcqNN97ImTNnKnQ/RUSkYpkMwzBcXYSIiEhZmThxIh999BGenp5Oyx999FGeeuopTCYTt99+O3PmzHF81r17dzp27Mg777zDe++9x6OPPsrhw4fx8fEBYPny5QwfPpxjx44REhJCvXr1uPnmm3nmmWfyrcFkMvHkk08yc+ZMABITE/Hz82P58uW690tEpBrTPVciIlLt9O/f3yk8AQQHBzve9+jRw+mzHj16sG3bNgB27dpFu3btHMEKoFevXthsNnbv3o3JZOLYsWMMGDCg0Bratm3reO/j44Ofnx8nTpwo6S6JiEgVoHAlIiLVjo+PT57L9C7GZDIBYBiG431+bby8vIq0PYvFkmddm81WrJpERKRq0T1XIiJS4/z000955lu0aAFAy5Yt2bZtG4mJiY7Pf/zxR8xmM82bN8fPz4+GDRuydu3aCq1ZREQqP/VciYhItZOamkpsbKzTMnd3d2rXrg3AZ599RufOnbn00kv5+OOP+eWXX5g7dy4AN954I9OmTWPChAlMnz6dkydPcvfddzNu3DhCQkIAmD59Orfffjt169ZlyJAhnD9/nh9//JG77767YndUREQqFYUrERGpdlauXElYWJjTsqioKP7++2/APpLfJ598wp133kloaCgff/wxLVu2BMDb25tvv/2We++9ly5duuDt7c3o0aN59dVXHduaMGECKSkpvPbaazz00EPUrl2ba665puJ2UEREKiWNFigiIjWKyWRi6dKljBw50tWliIhINaN7rkRERERERMqAwpWIiIiIiEgZ0D1XIiJSo+hqeBERKS/quRIRERERESkDClciIiIiIiJlQOFKRERERESkDChciYiIiIiIlAGFKxERERERkTKgcCUiIiIiIlIGFK5ERERERETKgMKViIiIiIhIGfh/US8VbsJf9cQAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import os\n",
    "os.environ['KMP_DUPLICATE_LIB_OK']='True'\n",
    "# Calculate and print accuracies for training and cross-validation sets\n",
    "model.eval()\n",
    "with torch.no_grad():\n",
    "    # Training set accuracy\n",
    "    tr_correct = 0\n",
    "    tr_total = 0\n",
    "    for images, labels in trLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        tr_total += labels.size(0)\n",
    "        tr_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    tr_accuracy = 100 * tr_correct / tr_total\n",
    "    \n",
    "    # Cross-validation set accuracy\n",
    "    cv_correct = 0\n",
    "    cv_total = 0\n",
    "    for images, labels in cvLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        cv_total += labels.size(0)\n",
    "        cv_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    cv_accuracy = 100 * cv_correct / cv_total\n",
    "\n",
    "print(f'Accuracy on training set: {tr_accuracy:.2f}%')\n",
    "print(f'Accuracy on cross-validation set: {cv_accuracy:.2f}%')\n",
    "\n",
    "# Plot training and cross-validation losses\n",
    "plt.figure(figsize=(10, 5))\n",
    "plt.plot(range(1, num_epochs+1), train_losses, label='Training Loss')\n",
    "plt.plot(range(1, num_epochs+1), cv_losses, label='Cross-Validation Loss')\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('Loss')\n",
    "plt.title('Training and Cross-Validation Loss')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b82491bc-6186-455d-bcfa-b0f4d9f8fbc9",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
